Developing a Search Component for KM Search iView

Table of Contents

 

Applies To:

Knowledge Management 6.0

Summary

Customizable search interfaces are absolutely necessary for providing company-specific search functionality for KM content. Since the introduction of functionality for creating search dialogs with search components, it is possible to develop customized search components and plug them into the standard search iView of KM.

 

Relevant Knowledge Management APIs

A prerequisite for developers starting search component implementation is an understanding of the concepts described in Repository Framework Concepts (RCO).

This tutorial describes the usage of the following Knowledge Management APIs that are relevant for implementing your own search component:

Coding in Detail

The standard KM search iView offers the capability of plugging in custom-developed search components that define certain areas of the iView. There is the following default iView layout:

Developing new search components means implementing the ISearchComponent interface. It is necessary to implement certain methods that are called by the standard search iView and that must return certain values. This sample search component shows a list of buzzwords which are added to the search term, if they are selected.

The sequence diagram of a single call stack is shown in the diagram below:

Implementing an ISearchComponent

The ISearchComponent interface offers some important method signatures to be implemented in order to get a valid search component.

To render the control in the standard search iView, an HTMLB compliant control has to be returned by the renderComponent() method:

    public Component renderComponent() throws SearchException {

For example, take any HTMLB layout object for defining a certain area within the standard search iView:

        GridLayout grid = new GridLayout();
        grid.setWidth("100%");
        grid.setCellPadding(5);
        
        grid.addComponent(2,1, this.createHeader());
        grid.addComponent(3,1, this.createBody());
        
        grid.addComponent(4,1, new HTMLFragment("<hr size=\"1\">"));
        return grid;
    }
				

The method should throw a SearchException when an error occurs during rendering.

The rendered HTMLB component can contain all HTMLB controls that can be used for input handling from the user, such as InputField, Checkbox, Radiobuttons:

    GridLayout grid = new GridLayout();
    grid.setWidth("100%");
    int col = 1, row = 1;
    
    for (int i=0;i<SimpleSearchComponent.m_buzzwords.length;i++) {
        if (i%7==0) {
            col = 1;
            row++;
        }
        Checkbox c = 
            new Checkbox(SimpleSearchComponent.m_buzzwords[i]);
        c.setText(value);
        c.setChecked(false);
				
        grid.addComponent(row , col, c);
        col ++;
    }
    return grid;
				

After the UI is rendered by the standard KM search iView and the user executes the search by pressing the search button, the UI elements of the rendered search component are evaluated by the standard KM search iView by calling the setDynpage() method. It provides access to every HTMLB element that is placed on the layout control:

    public void setDynPage(DynPage dynPage) {
        StringBuffer searchWord = new StringBuffer();
        Component c = null;
				

Retrieve all UI elements from the current Dynpage. Do not persist the dynpage object itself. It is created anew for every server roundtrip.

        for (int i=0;i<SimpleSearchComponent.m_buzzwords.length;i++) {
            c = dynPage.getComponentByName(
                SimpleSearchComponent.m_buzzwords[i]
            );
            if (c!=null && c instanceof Checkbox) {
                if (((Checkbox)c).isChecked()) {
                searchWord.append(c.getId());
                searchWord.append(SimpleSearchComponent.SEPARATOR);
                }
            }
        }
				

The values of every UI element can be stored in the local persistent map, which is validated for every server roundtrip for the corresponding search component:

        this.getPersistenceMap().setProperty(
            SimpleSearchComponent.PRP_SEARCH_WORDS, 
            searchWord.toString());
    }
				

The result of an executed search can be modified by adding a valid query (IQueryEntryList) created by the information specified in the UI elements. The query itself must be put in a SearchParamsMap object that contains search-relevant key value pairs:

    public SearchParamsMap getSearchParamsMap() {
        SearchParamsMap m = new SearchParamsMap();
        try {
            IQueryEntryList list = this.createQuery();
				

The IQueryEntryList must be put into the SearchParamsMap object with a certain key:

            m.put(SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES, list);
        } catch (WcmException e) {
            e.printStackTrace();
        }        
        return m;
    }
				

SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES key is evaluated by the standard KM search iView. You can put in the following subset of keys defined in the SearchParamConst class:

Parameter

Purpose

Type

Possible values

PARAM_SEARCH_IN

Search scope selection

String

SEARCH_INDEXES SEARCH_FROM_FOLDER (-> Search Folder)

PARAM_SEARCH_FOLDER

Search folder (-> PARAM_SEARCH_IN)

String

Example: /documents

PARAM_SEARCH_QUERY_ENTRIES

Search query list

IQueryEntryList

Complex object that can be built by SearchQueryBuilder

PARAM_INDICES_LIST

Index list to be searched on

ArrayList

Array list of index objects

PARAM_SORT_PROP_NAME

Property for sorting the search results

ISortPropertyName

CM property object with sort order (has major priority)

PARAM_SORT_ORDER

Sort order of search result

String

DESCENDING,ASCENDING

PARAM_SORT_OPTION

Property ID for sorting search results

String

PARAM_MATCHES_PER_PAGE

Number of search results per page

String

Numeric values: 5,10,20,50

PARAM_ALLOWED_SORT_PROPS

Property IDs of allowed sort properties to be shown in the search result header (csv)

String

Example: displayname,modified,modifiedby

PARAM_MAX_NOF_CATEGORIES

Maximum number of categories to be displayed for one search result

String

Numeric values: 0,1,2,3,4,6,9999

PARAM_MAX_SNIPPET_WORDS

Defines content snippet length for search result abstracts

String

Numeric values 0-200

PARAM_ENABLE_SEARCH_CASCADE

Enables cascaded search (see documentation)

Boolean

true,false

PARAM_SEARCH_TERM

Search term for display in search result header; is not taken into account for query

String

Example: Banana

PARAM_ERRORS_OCCURREDOCCURED (read-only)

Return value that indicates that at least one error occurred in at least one component; Is set to true when provided messageList of components is not empty; useful when input checks have to be performed;

Boolean

true, false

PARAM_JUST_SEARCHED (read-only)

Return value that indicates that a search was performed

Boolean

true

Keep in mind that all keys stored in the merged map of the standard KM search iView are overwritten by the last placed value, except the key SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES. This key’s values are connected by a logical AND.

In case no parameter is specified, the parameter’s values are taken from the defined Search option set. If no special option set is choosen the default values are taken. It is recommended to customize UI settings within the KM config iView -> Content Management -> UserInterface -> Search.

A helper method for creating valid IQueryEntryLists could look like this:

    private IQueryEntryList createQuery() throws WcmException {
        
        StringBuffer query = new StringBuffer();
        StringTokenizer words = new StringTokenizer(
                this.getPersistenceMap().getProperty(
                  SimpleSearchComponent.PRP_SEARCH_WORDS, ""
                ), SimpleSearchComponent.SEPARATOR);
				

Create a simple search term by concatenating a string object out of UI elements stored in the persistence map.

        while (words.hasMoreTokens()){
            query.append(words.nextToken());
        if (words.hasMoreTokens()) 
            query.append(SimpleSearchComponent.OPERATOR);
        }
				

Create a valid IQueryEntryList object retrieved from the standard SearchQueryBuilder instance.

        SearchQueryBuilder sqb = new SearchQueryBuilder();
        sqb.setSearchTerm(query.toString());
        
        return sqb.buildSearchQueryEntries();
    }
				

Alternatively, you can build your own IQueryEntryList objects retrieving an empty instance from the IFederatedSearch:

        IIndexService indexService =
            (IIndexService) ResourceFactory
                .getInstance()
                .getServiceFactory()
                .getService(
                IServiceTypesConst.INDEX_SERVICE);
				
        IFederatedSearch federatedSearch =
                (IFederatedSearch) indexService.getObjectInstance(
                    IWcmIndexConst.FEDERATED_SEARCH_INSTANCE);
        
        IQueryEntryList qel = federatedSearch.getNewQueryEntryList();
				
        IPropertyName propName = new PropertyName(
                        PropertyName.createDisplayname().getNamespace(),
                        earchParamConst.PROP_NAME_COLLECTION);
				

Create a query and set the important attributes and add a new entry to the entry list.

        IQueryEntry queryEntry = federatedSearch.getNewQueryEntry();
        queryEntry.setPropertyName(propName);
        queryEntry.setRowType(IQueryEntry.ROW_TYPE_ATTRIBUTE);
        queryEntry.setValue("true");
        queryEntry.setPropertyOperator(
            IQueryEntry.PROPERTY_OPERATOR_EQUAL
        );
        queryEntry.setTermWeight(1.0F);
				
        qel.add(queryEntry);
				

Methods to be implemented by an ISearchComponent implementation:

Method

Purpose

renderComponent()

Renders the custom search component based on an HTMLB layout, for example, a grid layout.

setDynPage()

Sets the current dynpage object from the standard KM search iView to evaluate user’s input.

getSearchParamsMap()

Returns a map with search relevant information. All parameters filled into the map are overwritten by the last placed call, except for SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES. This key’s values are merged by an logical AND

Configuration

After deployment of the search component within a valid PAR file structure, the technical mapping has to be carried out in the user interface configuration of the KM configuration iView.

The mapping from a Java class to a component alias can be carried out at Content Management -> User Interface -> Mapping -> Search Dialog Box Component. Create a new entry for the custom search component.

A unique alias and a valid java class must be provided. The java class specified here must implement the ISearchComponent interface and contain the methods mentioned above.

The search component is now registered in the KM infrastructure. It can be configured as a component of a certain component set. A search component set is used in a search iView instance:

The standard iView is now ready to use the search component. After you execute a search request, the following screen should appear:

Known limitations

Please keep in mind the following NetWeaver Notes. They describe some limitations in the current release:

OSS Note 743130: Section III. NW04 SP Stack 04: Content Management and Collaboration.

Sample SearchComponent

The following archive contains a valid and deployable SAP NetWeaver Developer Studio project based on KM API of NW04 SPS 4, which shows the steps described above in a whole example.

Download com.sap.netweaver.kmc.searchcomponent.zip